/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.vod.gauss.matrice;

import fr.vod.gauss.operations.Operation;

/**
 *
 * @author drazanakoto
 */
public class PivotDeGaussImpl extends PivotDeGauss {

    /**
     *
     * @param op
     */
    public PivotDeGaussImpl(Operation op) {
        super(op);
    }

    @Override
    public boolean resoudre(Matrice m) {

        if (m.getLength() == 0) {
            return false;
        }

        /**
         * triangulisation inférieur
         */
        for (int i = 0; i < m.getLength(); i++) {

            /**
             *
             */
            if (!getPivot(i, m)) {
                return false;
            }

            /**
             * mettre la diognal est à 1
             */
            mettreDiagonalUn(i, m.get(i));

            /**
             * mettre le colonne du pivot à zéro
             */
            for (int j = i + 1; j < m.getLength(); j++) {
                eliminer(i, m.get(i), m.get(j));
            }
        }

        // verifier tout les diagonal est égal à 1 diagonal et retourné faux dans le cas contraire 
        for (int i = 0; i < m.getLength(); i++) {
            if (m.get(i).get(i) != 1) {
                return false;
            }
        }

        //triangulisation supérieur
        for (int i = m.getLength() - 1; i > -1; i--) {
            /**
             * mettre le colonne du pivot à zéro
             */
            for (int j = i - 1; j > -1; j--) {
                eliminer(i, m.get(i), m.get(j));
            }
        }
        return true;
    }

    /**
     *
     * @param indice
     * @param e
     */
    protected void mettreDiagonalUn(int indice, Equation e) {
        int diagonal = e.get(indice);
        if (diagonal != 1 && diagonal != 0) {
            for (int i = 0; i < e.getSize(); i++) {
                e.setValueAt(i, op.division(e.get(i), diagonal));
            }
            e.setResult(op.division(e.getResult(), diagonal));
        }
    }

    /**
     *
     * @param c
     * @param pivot
     * @param l
     */
    protected void eliminer(int c, Equation pivot, Equation l) {
        int tmp = l.get(c);
        if (tmp != 0) {
            for (int i = 0; i < pivot.getSize(); i++) {
                l.setValueAt(i, op.soustraction(l.get(i), op.multiplication(pivot.get(i), tmp)));
            }
            l.setResult(op.soustraction(l.getResult(), op.multiplication(pivot.getResult(), tmp)));
        }
    }

    /**
     *
     * @param col
     * @param m
     * @return
     */
    protected boolean getPivot(int col, Matrice m) {
        int next = col;
        Equation tmp = m.get(next);

        while (tmp.get(col) == 0 && next < m.getLength()) {
            if (equationNull(next + 1, tmp)) {
                m.remove(next);
                return false;
            }
            next++;
            if (next < m.getLength()) {
                tmp = m.get(next);
            } else {
                return false;
            }
        }

        /**
         *
         */
        if (col != next) {
            m.move(next, col);
        }
        return true;
    }

    /**
     *
     * @param p
     * @param m
     * @return
     */
    protected boolean equationNull(int p, Equation m) {
        for (int i = p; i < m.getSize(); i++) {
            if (m.get(i) != 0) {
                return false;
            }
        }
        return true;
    }
}
